package xgenerator.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

public class HttpClient {
	
	/**
	 * GET
	 */
	private static final String GET_METHOD = "GET";
	
	/**
	 * POST
	 */
	private static final String POST_METHOD = "POST";
	
	/**
	 * 默认的连接超时
	 */
	public static final int DEFAULT_CONNECT_TIMEOUT = 5000;
	
	/**
	 * 默认的读取数据超时
	 */
	public static final int DEFAULT_READ_TIMEOUT = 10000;
	
	/**
	 * 默认的请求编码
	 */
	public static final String DEFAULT_REQUEST_ENCODING = "GBK";
	
	/**
	 * 默认的响应编码
	 */
	public static final String DEFAULT_RESPONSE_ENCODING = "GBK";

	/**
	 * 连接超时
	 */
	private int connectTimeout = DEFAULT_CONNECT_TIMEOUT;
	
	/**
	 * 读取数据超时
	 */
	private int readTimeout = DEFAULT_READ_TIMEOUT;

	/**
	 * 请求编码
	 */
	private String requestEncoding = DEFAULT_REQUEST_ENCODING;
	
	/**
	 * 响应编码
	 */
	private String responseEncoding;
	
	/**
	 * @return 连接超时(毫秒)
	 */
	public int getConnectTimeout() {
		return this.connectTimeout;
	}

	/**
	 * @return 读取数据超时(毫秒)
	 */
	public int getReadTimeout() {
		return this.readTimeout;
	}

	/**
	 * @return 请求编码
	 */
	public String getRequestEncoding() {
		return this.requestEncoding;
	}

	/**
	 * @param connectTimeout 连接超时(毫秒)
	 */
	public void setConnectTimeout(int connectTimeout) {
		this.connectTimeout = connectTimeout;
	}

	/**
	 * @param readTimeout 读取数据超时(毫秒)
	 */
	public void setReadTimeout(int readTimeout) {
		this.readTimeout = readTimeout;
	}

	/**
	 * @param requestEncoding 请求编码
	 */
	public void setRequestEncoding(String requestEncoding) {
		this.requestEncoding = requestEncoding;
	}

	/**
	 * @return the responseEncoding
	 */
	public String getResponseEncoding() {
		return responseEncoding;
	}

	/**
	 * @param responseEncoding the responseEncoding to set
	 */
	public void setResponseEncoding(String responseEncoding) {
		this.responseEncoding = responseEncoding;
	}

	/**
	 * 发送带参数的GET的HTTP请求
	 * @author <a href="mailto:shushanlee@msn.com">liss</a>
	 * @param requestUrl
	 * @param parameters
	 * @return
	 */
	public String doGet(String requestUrl, Map<String, String> parameters) {
		return doGet(requestUrl, parameters, DEFAULT_RESPONSE_ENCODING);
	}
	
	/**
	 * <pre>
	 * 发送带参数的GET的HTTP请求
	 * </pre>
	 * @param requestUrl HTTP请求URL
	 * @param parameters 参数映射表
	 * @return HTTP响应的字符串
	 */
	public String doGet(String requestUrl, Map<String, String> parameters, String responseEncoding) {
		return doRequest(GET_METHOD, requestUrl, parameters, responseEncoding);
	}

	/**
	 * 发送不带参数的GET的HTTP请求
	 * @author <a href="mailto:shushanlee@msn.com">liss</a>
	 * @param requestUrl
	 * @return
	 */
	public String doGet(String requestUrl) {
		return doGet(requestUrl, DEFAULT_RESPONSE_ENCODING);
	}
	
	/**
	 * <pre>
	 * 发送不带参数的GET的HTTP请求
	 * </pre>
	 * @param requestUrl HTTP请求URL
	 * @return HTTP响应的字符串
	 */
	public String doGet(String requestUrl, String responseEncoding) {
		setResponseEncoding(responseEncoding);
		
		HttpURLConnection httpConn = null;
		String responseContent = null;
		try {
			StringBuffer params = new StringBuffer();
			String queryUrl = requestUrl;
			int paramIndex = requestUrl.indexOf("?");

			if (paramIndex > 0) {
				queryUrl = requestUrl.substring(0, paramIndex);
				String parameters = requestUrl.substring(paramIndex + 1, requestUrl.length());
				String[] paramArray = parameters.split("&");
				for (int i = 0; i < paramArray.length; i++) {
					String oneParamStr = paramArray[i];
					int index = oneParamStr.indexOf("=");
					if (index > 0) {
						String parameter = oneParamStr.substring(0, index);
						String value = oneParamStr.substring(index + 1, oneParamStr.length());
						params.append(parameter);
						params.append("=");
						params.append(URLEncoder.encode(value, this.requestEncoding));
						params.append("&");
					}
				}

				params = params.deleteCharAt(params.length() - 1);
			}
			
			/*
			 * 打开链接
			 */
			httpConn = openConnection(queryUrl, GET_METHOD);
			
			/*
			 * 请求数据
			 */
			sendRequestData(httpConn.getOutputStream(), params.toString());

			/*
			 * 响应数据
			 */
			responseContent = getResponseText(httpConn.getInputStream());
		} catch (IOException e) {
			throw new RuntimeException(e);
		} finally {
			if (httpConn != null) {
				httpConn.disconnect();
			}
		}

		return responseContent;
	}

	/**
	 * 发送带参数的POST的HTTP请求
	 * @author <a href="mailto:shushanlee@msn.com">liss</a>
	 * @param requestUrl
	 * @param parameters
	 * @return
	 */
	public String doPost(String requestUrl, Map<String, String> parameters) {
		return doPost(requestUrl, parameters, DEFAULT_RESPONSE_ENCODING);
	}
	
	/**
	 * <pre>
	 * 发送带参数的POST的HTTP请求
	 * </pre>
	 * @param requestUrl HTTP请求URL
	 * @param parameters 参数映射表
	 * @return HTTP响应的字符串
	 */
	public String doPost(String requestUrl, Map<String, String> parameters, String responseEncoding) {
		return doRequest(POST_METHOD, requestUrl, parameters, responseEncoding);
	}
	
	/**
	 * 发送通用请求的方法
	 * @author <a href="mailto:shushanlee@msn.com">liss</a>
	 * @param method
	 * @param requestUrl
	 * @param parameters
	 * @param responseEncoding
	 * @return
	 */
	private String doRequest(String requestMethod, String requestUrl, Map<String, String> parameters, String responseEncoding) {
		setResponseEncoding(responseEncoding);
		
		HttpURLConnection httpConn = null;
		String responseContent = null;
		try {
			/*
			 * 打开链接
			 */
			httpConn = openConnection(requestUrl, requestMethod);
			
			/*
			 * 请求数据
			 */
			String requestParameters = parseRequestParameters(parameters);
			sendRequestData(httpConn.getOutputStream(), requestParameters);

			/*
			 * 响应数据
			 */
			responseContent = getResponseText(httpConn.getInputStream());
		} catch (IOException e) {
			throw new RuntimeException(e);
		} finally {
			if (httpConn != null) {
				httpConn.disconnect();
			}
		}
		return responseContent;
	}
	
	/**
	 * 打开连接
	 * @author <a href="mailto:shushanlee@msn.com">liss</a>
	 * @param requestUrl
	 * @param requestMethod
	 * @return
	 */
	private HttpURLConnection openConnection(String requestUrl, String requestMethod) {
		HttpURLConnection httpConn = null;
		try {
			URL url = new URL(requestUrl);
			httpConn = (HttpURLConnection) url.openConnection();
			httpConn.setRequestMethod(requestMethod);
			System.setProperty("sun.net.client.defaultConnectTimeout", String.valueOf(this.connectTimeout));// （单位：毫秒）jdk1.4换成这个,连接超时
			System.setProperty("sun.net.client.defaultReadTimeout", String.valueOf(this.readTimeout)); // （单位：毫秒）jdk1.4换成这个,读操作超时
//			httpURLConn.setConnectTimeout(5000);//（单位：毫秒）jdk
			// 1.5换成这个,连接超时
//			httpURLConn.setReadTimeout(5000);//（单位：毫秒）jdk 1.5换成这个,读操作超时
			httpConn.setDoOutput(true);
			httpConn.setDoInput(true);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return httpConn;
	}
	
	/**
	 * 解析请求参数
	 * @author <a href="mailto:shushanlee@msn.com">liss</a>
	 * @param parameters
	 * @return
	 */
	private String parseRequestParameters(Map<?, ?> parameters) {
		StringBuffer params = new StringBuffer();
		
		try {
			for (Iterator<?> iter = parameters.entrySet().iterator(); iter.hasNext();) {
				Entry<?, ?> element = (Entry<?, ?>) iter.next();
				params.append(element.getKey().toString());
				params.append("=");
				params.append(URLEncoder.encode(element.getValue().toString(), this.requestEncoding));
				params.append("&");
			}

			if (params.length() > 0) {
				params = params.deleteCharAt(params.length() - 1);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		return params.toString();
	}
	
	/**
	 * 发送请求数据
	 * @author <a href="mailto:shushanlee@msn.com">liss</a>
	 * @param os
	 * @param params
	 */
	private void sendRequestData(OutputStream os, String params) {
		try {
			byte[] bbuf = params.getBytes();
			os.write(bbuf, 0, bbuf.length);
			os.flush();
			os.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
	}
	
	/**
	 * 获取响应数据
	 * @author <a href="mailto:shushanlee@msn.com">liss</a>
	 * @param is
	 * @return
	 */
	private String getResponseText(InputStream is) {
		String responseContent = null;
		
		try {
			BufferedReader rd = new BufferedReader(new InputStreamReader(is, this.responseEncoding));
			StringBuffer tempStr = new StringBuffer();
			String crlf = System.getProperty("line.separator");  //#
			String tempLine = null;
			while (null != (tempLine = rd.readLine())) {
				tempStr.append(tempLine);
				tempStr.append(crlf);
			}
			responseContent = tempStr.toString();
			rd.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		return responseContent;
	}

	/**
	 * for test
	 * @author <a href="mailto:shushanlee@msn.com">liss</a>
	 * @param args
	 */
	public static void main(String[] args) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", "320");
		
		HttpClient httpClient = new HttpClient();
		httpClient.setRequestEncoding(HttpClient.DEFAULT_REQUEST_ENCODING);
		String requestUrl = "http://k.wps.cn/";
		String responseEncoding = "UTF-8";  //UTF-8、GBK
		
//		System.out.println(httpClient.doGet(requestUrl, responseEncoding));
		System.out.println(httpClient.doPost(requestUrl, map, responseEncoding));
	}

}
